package com.woniuxy.carlife.service.impl;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.woniuxy.carlife.param.CouponParam;
import com.woniuxy.carlife.param.FindCouponParam;
import com.woniuxy.carlife.domain.Coupon;
import com.woniuxy.carlife.mapper.CouponMapper;
import com.woniuxy.carlife.service.CouponService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.ObjectUtils;

import javax.annotation.Resource;
import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.concurrent.TimeUnit;

/**
 * @author fx
 * @ClassName:CouponServiceImpl
 * @Description: 优惠券service实现类
 * @date 2021/4/6 20:00
 **/

@Service
public class CouponServiceImpl extends ServiceImpl<CouponMapper, Coupon> implements CouponService {

    @Resource
    private CouponMapper couponMapper;

    @Resource
    private RedisTemplate redisTemplate;

    //声明一个集合存库存不足的优惠券id
    private ArrayList<Integer> cid=new ArrayList<Integer>();

    //注入加锁类
    @Resource
    private RedissonClient redissonClient;

    /**
     * 功能描述〈新增优惠券〉
     * @author:fx
     * @param: @param null:
     * @return:
     * @Date 2021/4/8 18:44
     * @throws
     */
    @Override
    public int saveCoupon(CouponParam coupon) {
        //先根据名称查redis
        String s =(String) redisTemplate.opsForValue()
                .get("com.woniuxy:carlife:serviceproject:coupon:" + coupon.getCouponName());
        if (ObjectUtils.isEmpty(s)){
            //根据名字查数据库
            Coupon coupon_name = couponMapper.selectOne(new QueryWrapper<Coupon>()
                    .eq("coupon_name", coupon.getCouponName()));
            if (!ObjectUtils.isEmpty(coupon_name)){
                //如果数据库有数据就先把这个优惠券名存到redis
                redisTemplate.opsForValue()
                        .set("com.woniuxy:carlife:serviceproject:coupon:" + coupon.getCouponName(),
                                coupon.getCouponName());
                //设置过期时间,5分钟
                redisTemplate.expire("com.woniuxy:carlife:serviceproject:coupon:" + coupon.getCouponName(),
                        5*60,TimeUnit.SECONDS);
                return -1;
            }
        }else{
            return -1;
        }
        Coupon coupon1 = new Coupon();
        //优惠券名称
        coupon1.setCouponName(coupon.getCouponName());
        //优惠券类别id
        coupon1.setCouponCategoryId(coupon.getCouponCategoryId());
        //优惠券分类(满减券/无门槛券等)
        coupon1.setCouponCategoryName(coupon.getCouponCategoryName());
        //满减优惠券额度(最低优惠的消费标准，默认为0)
        coupon1.setCouponPreferentialAmount(coupon.getCouponPreferentialAmount());
        //优惠金额
        coupon1.setCouponQuota(coupon.getCouponQuota());
        //优惠券有效期(按天数算)
        coupon1.setCouponExpireTime(coupon.getCouponExpireTime());
        //优惠券状态(已发放/未发放/删除/已领完),默认为未发放
        coupon1.setCouponStatus("未发放");
        //优惠券数量
        coupon1.setCouponNumber(coupon.getCouponNumber());
        //设置创建时间（当前时间）
        coupon1.setCouponCreateTime(new Timestamp(new Date().getTime()));
        //执行新增方法
        int insert = couponMapper.insert(coupon1);
        if (insert>0){
            return 1;
        }
        return 0;
    }

    /**
     * 功能描述〈多条件查询符合条件的优惠券，类别名称、优惠金额、状态、库存量范围〉
     * @author:fx
     * @param: @param null:
     * @return:
     * @Date 2021/4/8 18:45
     * @throws
     */
    @Override
    public List<Coupon> findCouponByCondition(FindCouponParam couponParam) {
        //先看输入了那些条件
        QueryWrapper<Coupon> qw = new QueryWrapper<>();
        //优惠券名称
        if (couponParam.getCouponName()!=null){
            qw.eq("coupon_name",couponParam.getCouponName());
        }
        //类别名称
        if (couponParam.getCouponCategoryName()!=null){
            qw.eq("coupon_category_name",couponParam.getCouponCategoryName());
        }
        //优惠券额度
        if(couponParam.getCouponQuota()!=null){
            qw.eq("coupon_quota",couponParam.getCouponQuota());
        }
        //优惠券状态
        if (couponParam.getCouponStatus()!=null){
            qw.eq("coupon_status",couponParam.getCouponStatus());
        }
        //优惠券剩余数量范围
        //最小范围
        if (couponParam.getCouponMinNumber()!=null){
            qw.gt("coupon_number",couponParam.getCouponMinNumber());
        }
        //最大范围
        if (couponParam.getCouponMaxNumber()!=null){
            qw.lt("coupon_number",couponParam.getCouponMaxNumber());
        }
        //执行查询操作
        List<Coupon> coupons = couponMapper.selectList(qw);
        return coupons;
    }

    /**
     * 功能描述〈根据优惠券id修改库存量并同时判断修改优惠券状态和修改时间，只修改redis中的数据〉
     * @author:fx
     * @param: @param null:
     * @return:
     * @Date 2021/4/8 19:02
     * @throws
     */
    @Override
    public boolean updateCouponNumByCouponIdFromRedis(Integer id)throws Exception {
        //加锁
        RLock lock = redissonClient.getLock("couponnum");

        //设置过期时间和等待时间
        boolean b = lock.tryLock(10, 15, TimeUnit.SECONDS);

        if (b){
            //加锁成功才执行方法
            //先从redis中查询
            String str = (String) redisTemplate.opsForHash()
                    .get("com.woniuxy:carlife:serviceproject:coupon", "id:" + id);
            Coupon coupon = null;
            if (ObjectUtils.isEmpty(str)){
                //redis没有数据就从数据库中查询
                coupon = couponMapper.selectById(id);
                if (ObjectUtils.isEmpty(coupon)){
                    return false;
                }
            }else{
                //把数据转换成对象
                coupon = JSON.parseObject(str, Coupon.class);
            }
            //先判断库存量是否足够，再把这个优惠券库存-1
            if (coupon.getCouponNumber()>=1){
                coupon.setCouponNumber(coupon.getCouponNumber()-1);
                //再存到redis中
                String string = JSON.toJSONString(coupon);
                redisTemplate.opsForHash()
                        .put("com.woniuxy:carlife:serviceproject:coupon",
                                "id:" + id,string);
            }else {
                //表示库存不足，直接把这个id对应的信息更新到数据库，在删除这个key
                int i = couponMapper.updateById(coupon);
                redisTemplate.opsForHash()
                        .delete("com.woniuxy:carlife:serviceproject:coupon","id:" + id);
                return false;
            }
        }else{
            //加锁失败
            return false;
        }
        //redisson方式解锁
        if (lock!=null) lock.unlock();
        //再把做了更改的id存起来，定时更新数据库时根据这些id更新
        redisTemplate.opsForList()
                .leftPush("com.woniuxy:carlife:serviceproject:coupon:id",id+"");
        return true;
    }

    /**
     * 功能描述〈定时修改优惠券库存量、状态、和修改时间，修改数据库〉
     * @author:fx
     * @param: @param null:
     * @return:
     * @Date 2021/4/8 19:10
     * @throws
     */
    @Override
    public boolean updateCouponNumByCouponIdToMySql() {
        //先从redis查做了更改的id集合
        List<String> range = redisTemplate.opsForList()
                .range("com.woniuxy:carlife:serviceproject:coupon:id", 0, -1);
        if (!ObjectUtils.isEmpty(range)){
            //如果不为空就循环便利这些id
            for (int i = 0; i <range.size() ; i++) {
                int id = Integer.parseInt(range.get(i));
                //再根据这些id到redis中查询数据，改优惠券库存量
                String str = (String) redisTemplate.opsForHash()
                        .get("com.woniuxy:carlife:serviceproject:coupon", "id:" + id);
                //转换为对象
                Coupon coupon = JSON.parseObject(str, Coupon.class);
                //修改数据到数据库
                couponMapper.updateById(coupon);
            }
            //再把库存不足的key删掉
//            for (Integer integer : cid) {
//                redisTemplate.opsForHash()
//                        .delete("com.woniuxy:carlife:serviceproject:coupon",
//                                "id:" + integer);
//            }
        }
        return true;
    }

    /**
     * 功能描述〈根据优惠券id查询详情〉
     * @author:fx
     * @param: @param null:
     * @return:
     * @Date 2021/4/12 18:57
     * @throws
     */
    @Override
    public Coupon findCouponInfoByCouponId(Integer couponId) {
        //先从redis中查询
        String str = (String) redisTemplate.opsForHash()
                .get("com.woniuxy:carlife:serviceproject:coupon", "id:" + couponId);
        Coupon coupon = null;
        if (ObjectUtils.isEmpty(str)){
            //redis没有数据就从数据库中查询
            coupon = couponMapper.selectById(couponId);
            //再存到redis中
            String string = JSON.toJSONString(coupon);
            redisTemplate.opsForHash()
                    .put("com.woniuxy:carlife:serviceproject:coupon",
                            "id:" + couponId,string);
        }else{
            //把数据转换成对象
            coupon = JSON.parseObject(str, Coupon.class);
        }
        return coupon;
    }
}
